﻿using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.Extensions.DependencyInjection;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.IO;
using System;
using Infrastructure.Extensions;
using JinianNet.JNTemplate;
using Microsoft.Extensions.Options;
using System.Text.Json;
using Microsoft.AspNetCore.DataProtection.KeyManagement;
using System.Text;

namespace Infrastructure.Filters
{
    [ResultModel(typeof(ApiResult<>))]
    public class ApiResultProvider : IResultProvider
    {

        /// <summary>
        /// 异常返回值
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public IActionResult OnException(ExceptionContext context)
        {
            var (code, mess) = context.GetException();
            return new JsonResult(new ApiResult<string>
            {
                Msg = mess,
                RequestId = HttpContextGlobal.CurrentTraceId,
                Code = code,
                Data = null,
                Success = false
            });
        }
        /// <summary>
        /// 成功返回值
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public IActionResult OnSucceeded(ActionExecutedContext context)
        {
            return new JsonResult(new ApiResult<object>
            {
                Msg = "success",
                RequestId = HttpContextGlobal.CurrentTraceId,
                Code = 200,
                Data = context.GetContext(),
                Success = true
            });
        }
        /// <summary>
        /// 验证失败返回值
        /// </summary>
        /// <param name="context"></param>
        /// <param name="modelStates"></param>
        /// <param name="validationResults"></param>
        /// <param name="validateFailedMessage"></param>
        /// <returns></returns>
        public IActionResult OnValidateFailed(ActionExecutingContext context, ModelStateDictionary modelStates, Dictionary<string, IEnumerable<string>> validationResults, string validateFailedMessage)
        {
            return new JsonResult(new ApiResult<object>
            {
                Msg = ConvertMessage(validationResults),
                RequestId = HttpContextGlobal.CurrentTraceId,
                Code = ResponseStateEnum.ParameterError.GetResponseStateCode(),
                Data = null,
                Success = false
            });
        }


        string ConvertMessage(Dictionary<string, IEnumerable<string>> validationResults)
        {
            if (validationResults == null || validationResults.Count() == 0)
            {
                return string.Empty;
            }
            StringBuilder sbMsg = new StringBuilder();
            int i = 0;
            foreach(var item in validationResults.Keys)
            {
                var messs = validationResults[item];
                if (messs == null || messs.Count() == 0)
                {
                    return string.Empty;
                }
                var tip=string.Join(",", messs);
                i++;
                sbMsg.Append($"{i}.{tip};\r\n");
            }
            return sbMsg.ToString();
        }

        public IActionResult OnFailed(HttpContext context, ResponseStateEnum responseStatus)
        {
            var (code, mess) = context.GetException(responseStatus);
            return new JsonResult(new ApiResult<object>
            {
                Msg = mess,
                RequestId = HttpContextGlobal.CurrentTraceId,
                Code = code,
                Success = false
            });
        }
        /// <summary>
        /// 处理输出状态码
        /// </summary>
        /// <param name="context"></param>
        /// <param name="statusCode"></param>
        /// <returns></returns>
        public async Task OnResponseStatusCodes(HttpContext context, int statusCode)
        {
            switch (statusCode)
            {
                // 处理 401 状态码
                case StatusCodes.Status401Unauthorized:
                    //The response cannot be cleared, it has already started sending.
                    await context.Response.WriteAsJsonAsync(new ApiResult<object>
                    {
                        Msg = "401 Unauthorized",
                        RequestId = HttpContextGlobal.CurrentTraceId,
                        Code = StatusCodes.Status401Unauthorized,
                        Data = null,
                        Success = false
                    });
                    break;
                // 处理 403 状态码
                case StatusCodes.Status403Forbidden:
                    await context.Response.WriteAsJsonAsync(new ApiResult<object>
                    {
                        Msg = "403 Unauthorized",
                        RequestId = HttpContextGlobal.CurrentTraceId,
                        Code = StatusCodes.Status403Forbidden,
                        Data = null,
                        Success = false
                    });
                    break;
                case StatusCodes.Status415UnsupportedMediaType:
                    await context.Response.WriteAsJsonAsync(new ApiResult<object>
                    {
                        Msg = "415 Unsupported MediaType",
                        RequestId = HttpContextGlobal.CurrentTraceId,
                        Code = StatusCodes.Status415UnsupportedMediaType,
                        Data = null,
                        Success = false
                    });
                    break;
                default:
                    break;
            }
        }

        public IActionResult OnValidateFailed(ResultExecutingContext context)
        {
            BadRequestObjectResult res = (BadRequestObjectResult)context.Result;
            ValidationProblemDetails obj = res.Value as ValidationProblemDetails;
            return new JsonResult(new ApiResult<object>
            {
                Msg = obj.Errors.ToJson(),
                RequestId = HttpContextGlobal.CurrentTraceId,
                Code = StatusCodes.Status400BadRequest,
                Data = null,
                Success = false
            });
        }

        public IActionResult OnAuthorizationFailed(AuthorizationFilterContext context, ResponseStateEnum responseStatus)
        {
            var metas = context.HttpContext.RequestServices.GetService<IDictionary<ResponseStateEnum, ResponseStateAttribute>>();
            return new JsonResult(new ApiResult<object>
            {
                Msg = metas[responseStatus].Message,
                RequestId = HttpContextGlobal.CurrentTraceId,
                Code = metas[responseStatus].Code,
                Data = null,
                Success = false
            });
        }

    }
}